package test_pkg

import (
	"fmt"
	"strconv"
	"strings"
)

type ParseError struct {
	Index int
	Word  string
	Err   error
}

// 类型定义了 String() 方法，它会被用在 fmt.Printf() 中生成默认的输出：等同于使用格式化描述符 %v 产生的输出。
// 还有 fmt.Print() 和 fmt.Println() 也会自动使用 String() 方法。
// 不要在 String() 方法里面调用涉及 String() 方法的方法，它会导致意料之外的错误
func (e *ParseError) String() string {
	return fmt.Sprintf("pkg parse: error parsing %q as int", e.Word) //Sprintf 格式化字符串，可以作为结果返回  Printf 格式化打印
}

func Parse(intput string) (numbers []int, err error) {
	defer func() {
		if e := recover(); e != nil {
			var ok bool
			err, ok = e.(error)
			if !ok {
				err = fmt.Errorf("pkg: %v", e)
			}
		}
	}() //最后的一对括号表示对该匿名函数的调用

	fields := strings.Fields(intput)
	numbers = fields2numbers(fields)
	return
}

func fields2numbers(fields []string) (numbers []int) {
	if len(fields) == 0 {
		panic("no words to parse")
	}

	for i, v := range fields {
		num, err := strconv.Atoi(v)
		if err != nil {
			panic(&ParseError{i, v, err})
		}

		numbers = append(numbers, num)
	}

	return
}

func Test_recover2() {
	var examples = []string{
		"1 2 3 4 5",
		"100 50 25 12.5 6.25",
		"2 + 2 = 4",
		"1st class",
		"",
	}

	for _, ex := range examples {
		fmt.Printf("Parsing %q:\n  ", ex)
		nums, err := Parse(ex)
		if err != nil {
			fmt.Println(err) // here String() method from ParseError is used
			continue
		}
		fmt.Println(nums)
	}
}
